/*
 * Copyright (c) 2009 John Pritchard, WTKX Project Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package wtkx;

import wtkx.be.Function;
import wtkx.co.ArrayList;
import wtkx.co.List;
import wtkx.co.ResourceCacheDictionary;
import wtkx.in.RepaintJump;
import wtkx.in.Screen;
import wtkx.io.CC;
import wtkx.io.CSS;
import wtkx.io.Hex;

import wtkx.ui.Align;
import wtkx.ui.Border;
import wtkx.ui.Display;
import wtkx.ui.Effects;
import wtkx.ui.Threads;
import wtkx.ui.Cursor;
import wtkx.ui.Direction;
import wtkx.ui.DragSource;
import wtkx.ui.DropTarget;
import wtkx.ui.Insets;
import wtkx.ui.Keyboard;
import wtkx.ui.Layout;
import wtkx.ui.Mouse;
import wtkx.ui.Orientation;
import wtkx.ui.Scrolling;
import wtkx.ui.View;

import jbxml.Dictionary;
import jbxml.Reflector;
import jbxml.Relative;
import jbxml.Resolver;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;


/**
 * <h3>Coordinate spaces</h3>
 * 
 * The coordinate space of a Component is that internal to (or
 * relative to) its parent Component.  In the special case of the root
 * of the scene graph, {@link Scene}, its parent is null and its
 * coordinate space can be called absolute, or the logical root.
 * 
 * <h3>Logical dimensions</h3>
 * 
 * All dimensions are "logical", meaning as declared in the WTKX file.
 * Scaling is handled by {@link Scene} paint.
 * 
 * <h3>WTKX Events</h3>
 * 
 * Event handlers are methods defined on the {@link Application} class
 * and named in WTKX attributes.  Method names are simple java
 * identifier strings without signature.
 * 
 * These methods are defined with the signatures as found in this
 * class (and reflected in the {@link wtkx.be.Function$Type
 * Function.Type} signature).
 * 
 * The following WTKX event attributes are defined here and available
 * for binding from WTKX to {@link Application} java methods.
 * 
 * <pre>
 * onload
 * onunload
 * onclick
 * ondblclick
 * onmousedown
 * onmouseup
 * onmouseover
 * onmousemove
 * onmouseout
 * onmousewheel
 * onfocus
 * onblur
 * onkeypress
 * onkeydown
 * onkeyup
 * onsubmit
 * onreset
 * onselect
 * onchange
 * </pre>
 * 
 * The following of these are generated by subclasses or application
 * programming.
 * 
 * <pre>
 * onchange
 * onreset
 * onselect
 * onsubmit
 * </pre>
 * 
 * @author gbrown
 * @author jdp
 */
public abstract class Component
    extends ArrayList<Component>
    implements jbxml.Component.Parent,
               jbxml.Component.Child
{

    protected final static BasicStroke DefaultStroke = new BasicStroke(1f);


    private static volatile Component FocusedComponent = null;

    public final static Component GetFocusedComponent() {
        return FocusedComponent;
    }
    private static boolean SetFocusedComponent(Component component) {
        if (null != component){

            boolean focusable = (component.isFocusable());

            Component previousFocusedComponent = Component.FocusedComponent;

            if (previousFocusedComponent != component) {

                if (focusable)
                    Component.FocusedComponent = component;
                else
                    Component.FocusedComponent = null;

                if (previousFocusedComponent != null) {
                    previousFocusedComponent.focusChanged(false);
                }

                component.focusChanged(true);

                return true;
            }
        }
        return false;
    }

    public final static void ClearFocus() {
        Component previousFocusedComponent = Component.FocusedComponent;

        Component.FocusedComponent = null;

        if (null != previousFocusedComponent && null != previousFocusedComponent.parent)
            previousFocusedComponent.focusChanged(false);

    }

    public final static String Name(URL url){
        if (null != url){
            String p = url.getPath();
            if (null != p){
                int idx = p.lastIndexOf('/');
                if (0 < idx)
                    return p.substring(idx+1);
                else
                    return p;
            }
        }
        return "";
    }



    protected final int identity;
    protected final String identityString;

    protected volatile Application application;

    protected volatile Component parent;

    protected volatile float x, y, width, height;    //(loc in parent, dim logical)

    protected volatile boolean visible;              //(painting)

    protected volatile boolean floating;             //(not in layout, e.g. Path)

    protected volatile boolean enabled;              //(accepting input)

    protected volatile boolean valid;                //(false:= needs validation)

    protected boolean validateTopDown;               //(true:= validate this then children)

    protected boolean focusableComponent;            //(false:= may not focus here)

    protected volatile boolean loading = true;       //(call onload in validation)

    protected volatile boolean centered;             //(auto layout feature)

    protected volatile boolean submit;

    protected final Effects effects = new Effects();

    protected volatile float componentEffectingX,    //(internal state)
                             componentEffectingY;

    protected volatile Cursor cursor;

    protected volatile Font font;                    //(use get to include)

    protected volatile FontMetrics fontMetrics;      //(use get for coherence)

    protected volatile Color color, backgroundColor; //(use get to include)
    
    protected volatile Color selectionColor;

    protected volatile Border border = new Border(); //(always not null)

    protected volatile Border borderFocused;

    protected volatile Insets padding = new Insets();//(always not null)

    protected volatile Insets margin = new Insets(); //(always not null)

    protected volatile Display display = new Display(Display.Type.Block);

    protected volatile boolean auto, autoPosX, autoPosY, autoDimW, autoDimH;

    protected volatile Orientation orientation = null;

    protected Function fOnload, fOnunload, fOnclick, fOndblclick, fOnmousedown, fOnmouseup, fOnmouseover,
        fOnmousemove, fOnmouseout, fOnmousewheel, fOnfocus, fOnblur, fOnkeypress, fOnkeydown, fOnkeyup,
        fOnsubmit, fOnreset, fOnselect, fOnchange, fReader, fWriter, fResponse, fRequest;

    protected volatile DragSource dragSource;

    protected volatile DropTarget dropTarget;

    protected volatile boolean mouseOver;

    protected volatile Component mouseOverComponent = null;
    protected volatile Component mouseDownComponent = null;
    protected volatile long mouseDownTime = 0;
    protected volatile int mouseClickCount = 0;
    protected volatile boolean mouseClickConsumed = false;

    protected Reflector reflect;

    protected String id;

    protected URL documentBase;

    protected volatile View view;

    protected volatile Align align;

    protected volatile Scrolling scrolling;

    protected String target;

    protected Component targetComponent;

    protected java.lang.Object targetObject;

    protected boolean transfersFocus;


    public Component() {
        super();
        this.visible = true;
        this.enabled = true;
        this.auto = true;
        this.validateTopDown = false; //(see container)
        this.orientation = Orientation.HORIZONTAL;
        this.view = View.None;

        this.setCursor(Cursor.DEFAULT);

        this.identity = System.identityHashCode(this);
        this.identityString = this.getClass().getName()+'/'+Hex.Encode(this.identity);
    }



    public Component clone(){
        Component clone = (Component)super.clone();
        return clone;
    }
    public void destroy(){
        Reflector reflect = this.reflect;
        if (null != reflect){
            this.reflect = null;
            reflect.destroy();
        }
        this.parent = null;
        this.application = null;
        this.effects.destroy();
        this.fOnload = null;
        this.fOnunload = null;
        this.fOnclick = null;
        this.fOndblclick = null;
        this.fOnmousedown = null;
        this.fOnmouseup = null;
        this.fOnmouseover = null;
        this.fOnmousemove = null;
        this.fOnmouseout = null;
        this.fOnfocus = null;
        this.fOnblur = null;
        this.fOnkeypress = null;
        this.fOnkeydown = null;
        this.fOnkeyup = null;
        this.fOnsubmit = null;
        this.fOnreset = null;
        this.fOnselect = null;
        this.fOnchange = null;
        this.fResponse = null;
        this.fRequest = null;
        this.fReader = null;
        this.fWriter = null;
        this.dragSource = null;
        this.dropTarget = null;
        this.mouseOverComponent = null;
        this.mouseDownComponent = null;
        for (Component child : this){
            child.destroy();
        }
        this.clear();
        this.scrolling = null;
    }
    public final Reflector getReflect(){
        Reflector reflect = this.reflect;
        if (null != reflect)
            return reflect;
        else {
            reflect = new Reflector(this);
            this.reflect = reflect;
            return reflect;
        }
    }
    public final boolean hasRelative(String name){
        return this.getReflect().hasRelative(name);
    }
    public final Relative getRelative(String name){
        return this.getReflect().getRelative(name);
    }
    public Relative setRelative(String name, String value){
        return this.getReflect().setRelative(name,value);
    }
    public final Number getRelativeValue(String name, Number number){
        return this.getReflect().getRelativeValue(name, number);
    }
    public final void dropRelative(String name){
        this.getReflect().dropRelative(name);
    }
    public final java.util.Iterator<String> relatives(){
        return this.getReflect().relatives();
    }
    /**
     * Called from WTKX Start Element for this element
     */
    public final void startElement(Reflector reflect){
        if (null == this.reflect)
            this.reflect = reflect;
        else
            throw new IllegalStateException();
    }
    /**
     * Called from WTKX Start Element for child element
     */
    public final void startElement(jbxml.Component child){
        if (child instanceof Component){
            Component comp = (Component)child;
            this.add(comp);
        }
        else if (child instanceof wtkx.Object){
            this.getWindow().getObjects().add( (wtkx.Object)child);
        }
    }
    /**
     * Called from WTKX End Element  
     * 
     * Calls 'layout'.
     */
    public void endElement(){
    }
    public final Component getParent() {
        return this.parent;
    }
    /**
     * Called before 'init'.
     */
    public void setParent(jbxml.Component parent) {

        if (parent == null && (isFocused() || isAncestor(GetFocusedComponent()))){
            ClearFocus();
        }
        if (null == parent || parent instanceof Component)
            this.parent = (Component)parent;
        else 
            throw new IllegalStateException(parent.getClass().getName());
    }
    public final List<Component> getChildren(){
        return this;
    }
    public final boolean hasChildren(){
        return (0 < this.getLength());
    }
    public final boolean hasNotChildren(){
        return (1 > this.getLength());
    }
    public final boolean hasEffects(){
        return (0 < this.effects.getLength());
    }
    public final boolean hasNotEffects(){
        return (1 > this.effects.getLength());
    }
    public final int add(Component child){
        if (null != child){
            child.setParent(this);
            int re = super.add(child);
            this.invalidate();
            return re;
        }
        else
            return -1;
    }
    public final int remove(Component child){
        if (null != child){
            child.setParent(null);
            
            int re = super.remove(child);
            this.invalidate();
            return re;
        }
        else
            return -1;
    }
    public final Alert alert(Alert.MessageType type, String message){
        try {
            Alert alert = new Alert(type,message);
            alert.startup(this.getScene(),this.getProperties());
            return alert;
        }
        catch (IOException exc){
            exc.printStackTrace();
            throw new RuntimeException(type.toString());
        }
    }
    public final Alert alert(Alert.MessageType type, Throwable thrown){
        try {
            Alert alert = new Alert(type,thrown);
            alert.startup(this.getScene(),this.getProperties());
            return alert;
        }
        catch (IOException exc){
            exc.printStackTrace();
            throw new RuntimeException(type.toString(),thrown);
        }
    }
    public final Alert alertStop(String message){
        return this.alert(Alert.MessageType.Stop,message);
    }
    public final Alert alertStop(Throwable thrown){
        return this.alert(Alert.MessageType.Stop,thrown);
    }
    public final Alert alertGo(String message){
        return this.alert(Alert.MessageType.Go,message);
    }
    public final Alert alertGo(Throwable thrown){
        return this.alert(Alert.MessageType.Go,thrown);
    }
    public final Alert alertTimeout(String message){
        return this.alert(Alert.MessageType.Timeout,message);
    }
    public final Alert alertTimeout(Throwable thrown){
        return this.alert(Alert.MessageType.Timeout,thrown);
    }
    public final Alert alertBroken(String message){
        return this.alert(Alert.MessageType.Broken,message);
    }
    public final Alert alertBroken(Throwable thrown){
        return this.alert(Alert.MessageType.Broken,thrown);
    }
    /**
     * @return Requires 'init'
     */
    public final Window open(String path)
        throws IOException
    {
        return this.open(this.getInputURL(path));
    }
    /**
     * @return Requires 'init'
     */
    public final Window open(String id, String path)
        throws IOException
    {
        return this.open(id,this.getInputURL(path));
    }
    /**
     * @return Requires 'init'
     */
    public final Window open(URL url)
        throws IOException
    {
        return this.open(null,url);
    }
    /**
     * @return Requires 'init'
     */
    public final Window open(String id, URL url)
        throws IOException
    {
        Scene scene = this.getScene();
        Dictionary<String, String> properties = this.getProperties();

        wtkx.io.WTKX reader = new wtkx.io.WTKX(scene,properties);
        Window window = (Window)reader.readObject(url);
        window.setResolver(reader);
        if (null != id){
            this.close(id);
            this.setObjectById(id,window);
        }
        window.open(scene);
        return window;
    }
    /**
     * @return Requires 'init'
     */
    public final Window open(String id, InputStream content)
        throws IOException
    {
        Scene scene = this.getScene();
        Dictionary<String, String> properties = this.getProperties();

        wtkx.io.WTKX reader = new wtkx.io.WTKX(scene,properties);
        Window window = (Window)reader.readObject(content);
        window.setResolver(reader);
        if (null != id){
            this.close(id);
            this.setObjectById(id,window);
        }
        window.open(scene);
        return window;
    }
    protected final void open(Scene scene){
        if (null == scene)
            throw new IllegalArgumentException();

        else if (null == this.parent ||
                 /*
                  * WTKX sets parent on the root of the scene graph
                  * without adding -- for 'setStyle' and similar
                  * requiring 'Scene'.
                  */
                 (scene == this.parent && 0 > scene.indexOf(this)))
        {
            ClearFocus();

            scene.add(this);
        }
        else
            throw new IllegalStateException("This component is in a scene graph.");
    }
    /**
     * Unlink from parent and destroy.  Should destroy this after the
     * close method returns for it to be garbage collected.
     */
    public final void close(){

        ClearFocus();

        Component parent = this.parent;
        if (null != parent){
            try {
                this.onunload(this);

                parent.remove(this);
            }
            finally {
                this.destroy();
            }
        }
    }
    public final void close(String id){
        java.lang.Object object = this.removeObjectById(id);
        if (object instanceof Component){
            Component component = (Component)object;
            component.close();
        }
    }
    public final Component updateAppend(String id, String at, String with){
        java.lang.Object object = this.getObjectById(id);
        if (object instanceof Component){
            Component component = (Component)object;
            return component.updateAppend(at,with);
        }
        else
            return null;
    }
    public final Component updateInsert(String id, String at, int idx, String with){
        java.lang.Object object = this.getObjectById(id);
        if (object instanceof Component){
            Component component = (Component)object;
            return component.updateInsert(at,idx,with);
        }
        else
            return null;
    }
    public final Component updateReplace(String id, String at, String search, String with){
        java.lang.Object object = this.getObjectById(id);
        if (object instanceof Component){
            Component component = (Component)object;
            return component.updateReplace(at,search,with);
        }
        else
            return null;
    }
    public final Component updateDelete(String id, String at, int start, int end){
        java.lang.Object object = this.getObjectById(id);
        if (object instanceof Component){
            Component component = (Component)object;
            return component.updateDelete(at,start,end);
        }
        else
            return null;
    }
    public final Component updateAppend(String at, String with){
        Reflector reflector = this.reflect;
        java.lang.Object value = reflector.get(at);
        if (null != value){
            if (value instanceof jbxml.Value){
                jbxml.Value bvalue = (jbxml.Value)value;
                String string = bvalue.toString();
                string += with;
                bvalue.fromString(string);
            }
            else {
                String string = value.toString();
                string += with;
                reflector.put(at,string);
            }
        }
        else
            reflector.put(at,with);
        return this;
    }
    public final Component updateInsert(String at, int idx, String with){
        Reflector reflector = this.reflect;
        java.lang.Object value = reflector.get(at);
        if (null != value){
            if (value instanceof jbxml.Value){
                jbxml.Value bvalue = (jbxml.Value)value;
                StringBuilder string = new StringBuilder(bvalue.toString());
                string.insert(idx,with);
                bvalue.fromString(string.toString());
            }
            else {
                StringBuilder string = new StringBuilder(value.toString());
                string.insert(idx,with);
                reflector.put(at,string.toString());
            }
        }
        return this;
    }
    public final Component updateReplace(String at, String search, String with){
        Reflector reflector = this.reflect;
        java.lang.Object value = reflector.get(at);
        if (null != value){
            if (value instanceof jbxml.Value){
                jbxml.Value bvalue = (jbxml.Value)value;
                StringBuilder string = new StringBuilder(bvalue.toString());
                int start = string.indexOf(search);
                if (-1 < start){
                    int end = (start+search.length());
                    string.replace(start,end,with);
                    bvalue.fromString(string.toString());
                }
            }
            else {
                StringBuilder string = new StringBuilder(value.toString());
                int start = string.indexOf(search);
                if (-1 < start){
                    int end = (start+search.length());
                    string.replace(start,end,with);
                }
                reflector.put(at,string.toString());
            }
        }
        return this;
    }
    public final Component updateDelete(String at, int start, int end){
        Reflector reflector = this.reflect;
        java.lang.Object value = reflector.get(at);
        if (null != value){
            if (value instanceof jbxml.Value){
                jbxml.Value bvalue = (jbxml.Value)value;
                StringBuilder string = new StringBuilder(bvalue.toString());
                string.delete(start,end);
                bvalue.fromString(string.toString());
            }
            else {
                StringBuilder string = new StringBuilder(value.toString());
                string.delete(start,end);
                reflector.put(at,string.toString());
            }
        }
        return this;
    }
    public final List<Effect> getEffects() {
        return effects;
    }
    public Scene getScene() {
        Component component = this;

        while (component != null && !(component instanceof Scene)) {
            component = component.parent;
        }

        return (Scene)component;
    }
    public Window getWindow() {
        Component component = this;

        while (component != null && !(component instanceof Window)) {
            component = component.parent;
        }

        return (Window)component;
    }
    public Form getForm() {
        Component component = this;

        while (component != null && !(component instanceof Form)) {
            component = component.parent;
        }

        return (Form)component;
    }
    public Screen getScreen(){
        Scene scene = this.getScene();
        if (null != scene)
            return scene.getScreen();
        else
            return null;
    }
    public Dictionary<String, String> getProperties(){
        Scene scene = this.getScene();
        if (null != scene)
            return scene.getProperties();
        else
            return null;
    }
    public final Application getApplication() {
        return this.application;
    }
    public final Application getSceneApplication() {
        Scene scene = this.getScene();
        if (null != scene)
            return scene.getApplication();
        else
            return null;
    }
    public java.awt.Container getHostContainer() {
        Scene scene = this.getScene();
        if (null != scene)
            return scene.getHostContainer();
        else
            return null;
    }
    public java.awt.Component getHostComponent() {
        Scene scene = this.getScene();
        if (null != scene)
            return scene.getHostComponent();
        else
            return null;
    }
    public Resolver getResolver(){
        Window window = this.getWindow();
        if (null != window)
            return window.getResolver();
        else
            return null;
    }
    public java.lang.Object getObjectById(String id){
        Window window = this.getWindow();
        if (null != window)
            return window.getObjectById(id);
        else
            return null;
    }
    public void setObjectById(String id, java.lang.Object value){
        Window window = this.getWindow();
        if (null != window)
            window.setObjectById(id,value);
        else
            throw new IllegalStateException();
    }
    public java.lang.Object removeObjectById(String id){
        Window window = this.getWindow();
        if (null != window)
            return window.removeObjectById(id);
        else
            return null;
    }
    public ResourceCacheDictionary getResourceCache(){
        return this.getScene().getResourceCache();
    }
    public java.awt.Robot getRobot()
        throws java.awt.AWTException
    {
        return this.getScene().getRobot();
    }
    public final String getId(){
        return this.id;
    }
    public final void setId(String id){
        this.id = id;
    }
    public boolean hasDocumentBase(){
        if (null != this.documentBase)
            return true;
        else {
            Component parent = this.parent;
            if (null != parent)
                return parent.hasDocumentBase();

            return false;
        }
    }
    public URL getDocumentBase(){
        URL documentBase = this.documentBase;
        if (null == documentBase){
            Component parent = this.parent;
            if (null != parent)
                return parent.getDocumentBase();
        }
        return documentBase;
    }
    public final void setDocumentBase(URL documentBase){
        this.documentBase = documentBase;
    }
    public final java.io.InputStream getInputStream(String path)
        throws IOException
    {
        URL url = this.getInputURL(path);
        if (null != url)
            return url.openStream();
        else
            return null;
    }
    public URL getInputURL(String path){
        if (this.hasDocumentBase()){
            URL documentBase = this.getDocumentBase();
            try {
                return new URL(documentBase,path);
            }
            catch (java.net.MalformedURLException exc){
                exc.printStackTrace();
            }
        }

        Scene scene = this.getScene();
        if (null != scene && scene != this)
            return scene.getInputURL(path);
        else
            return null;
    }
    public final float getX(){
        return this.x;
    }
    public final boolean hasX(){
        return (0f != this.x);
    }
    public final void setX(float x){
        this.x = x;
    }
    public final void setX(String string){
        if (null != string)
            try {
                this.x = Float.parseFloat(string);
            }
            catch (NumberFormatException exc){
                if ("auto".equals(string))
                    this.autoPosX = true;
                else
                    throw exc;
            }
    }
    public final int getIntX(){
        return (int)this.x;
    }
    public final float getY(){
        return this.y;
    }
    public final boolean hasY(){
        return (0f != this.y);
    }
    public final void setY(float y){
        this.y = y;
    }
    public final void setY(String string){
        if (null != string)
            try {
                this.y = Float.parseFloat(string);
            }
            catch (NumberFormatException exc){
                if ("auto".equals(string))
                    this.autoPosY = true;
                else
                    throw exc;
            }
    }
    public final int getIntY(){
        return (int)this.y;
    }
    public boolean hasWidth() {
        return (0f != this.width);
    }
    public boolean hasWidthAuto() {
        return (0f != this.width)&&(!this.autoDimW);
    }
    public float getWidth() {
        return this.width;
    }
    public final void setWidth(float w){
        if (0f <= w)
            this.width = w;
    }
    public final void setWidth(String string){
        if (null != string)
            try {
                this.width = Float.parseFloat(string);
            }
            catch (NumberFormatException exc){
                if ("auto".equals(string))
                    this.autoDimW = true;
                else
                    throw exc;
            }
    }
    public final int getIntWidth() {
        return (int)this.width;
    }
    public final float getParentInnerWidth(){
        Component parent = this.parent;
        if (null == parent)
            return 0f;
        else
            return parent.getInnerWidth();
    }
    public final float getInnerWidth(){
        float width = this.width;
        if (0f == width)
            width = this.getParentInnerWidth();

        return (width-this.getPaddingHorizontal());
    }
    public float getHeight() {
        return this.height;
    }
    public boolean hasHeight() {
        return (0f != this.height);
    }
    public boolean hasHeightAuto() {
        return (0f != this.height)&&(!this.autoDimH);
    }
    public final void setHeight(float h){
        if (0f <= h)
            this.height = h;
    }
    public final void setHeight(String string){
        if (null != string)
            try {
                this.height = Float.parseFloat(string);
            }
            catch (NumberFormatException exc){
                if ("auto".equals(string))
                    this.autoDimH = true;
                else
                    throw exc;
            }
    }
    public final int getIntHeight() {
        return (int)this.height;
    }
    public final float getParentInnerHeight(){
        Component parent = this.parent;
        if (null == parent)
            return 0f;
        else
            return parent.getInnerHeight();
    }
    public final float getInnerHeight(){
        float height = this.height;
        if (0f == height)
            height = this.getParentInnerHeight();

        return (height-this.getPaddingVertical());
    }
    public final Dimension getSize() {
        return new Dimension( (int)this.width, (int)this.height);
    }
    public final Rectangle getBounds(){
        return new Rectangle( (int)this.x, (int)this.y, (int)this.width, (int)this.height);
    }
    public final Rectangle2D.Float getBounds2D(){
        return new Rectangle2D.Float( this.x, this.y, this.width, this.height);
    }
    public final Rectangle2D.Float getBoundsInside(){
        float x = this.padding.left;
        float y = this.padding.top;
        float w = this.width;
        if (0f < w)
            w -= (this.padding.left+this.padding.right);
        else
            w = (this.padding.left+this.padding.right);
        float h = this.height;
        if (0f < h)
            h -= (this.padding.top+this.padding.bottom);
        else
            h = (this.padding.top+this.padding.bottom);

        return new Rectangle2D.Float( x, y, w, h);
    }
    public Shape getBorderOutline(){
        return new Rectangle2D.Float( 0f, 0f, (this.width-1f), (this.height-1f));
    }
    public final Rectangle getBoundsEffecting() {
        Rectangle2D.Float r2 = this.getBoundsEffecting2D();
        return new Rectangle((int)r2.x,(int)r2.y,(int)r2.width,(int)r2.height);
    }
    public final Rectangle2D.Float getBoundsEffecting2D(){
        Rectangle2D.Float bounds = this.effects.getBounds2D(this,(new Rectangle2D.Float( 0f, 0f, this.width, this.height)));

        float ex = bounds.x;
        float ey = bounds.y;
        if (0f == ex)
            this.componentEffectingX = 0f;
        else 
            this.componentEffectingX = -(ex);

        if (0f == ey)
            this.componentEffectingY = 0f;
        else 
            this.componentEffectingY = -(ey);

        bounds.x += this.x;
        bounds.y += this.y;
        return bounds;
    }
    public final void setSize(Dimension size) {
        if (null != size)
            this.setSize(size.width, size.height);
    }
    public final void setSize(float width, float height) {
        if (width < 0f)
            throw new IllegalArgumentException("width is negative.");
        else if (height < 0f)
            throw new IllegalArgumentException("height is negative.");
        else {
            float previousWidth = this.width;
            float previousHeight = this.height;

            if (width != previousWidth || height != previousHeight) {
                this.width = width;
                this.height = height;
                invalidate();
            }
        }
    }
    public final void setInnerWidth(float w){
        this.setWidth(w+this.getPaddingHorizontal());
    }
    public final void setInnerHeight(float h){
        this.setHeight(h+this.getPaddingVertical());
    }
    public final void setInnerSize(float w, float h){
        this.setSize(w+this.getPaddingHorizontal(),h+this.getPaddingVertical());
    }
    public final Point getLocation() {
        return new Point( (int)this.x, (int)this.y);
    }
    public final Point2D.Float getLocation2D() {
        return new Point2D.Float( this.x, this.y);
    }
    public void setLocation(float x, float y) {
        float previousX = this.x;
        float previousY = this.y;

        if (previousX != x || previousY != y) {
            this.x = x;
            this.y = y;
            this.invalidate();
        }
    }
    public final void setLocation(Point location) {
        if (null != location)
            setLocation(location.x, location.y);
    }
    public final void setLocation(Point2D.Float location) {
        if (null != location)
            setLocation(location.x, location.y);
    }
    public final boolean isVisible() {
        return visible;
    }
    public final boolean isNotVisible() {
        return (!visible);
    }
    public final void setVisible(boolean visible) {
        if (this.visible != visible) {

            if (!visible) {
                if (isFocused() || containsFocus()) {
                    ClearFocus();
                }

                if (mouseOver) {
                    mouseOut();
                }
            }

            this.visible = visible;

            if (visible)
                invalidate();
        }
    }
    public final boolean isFloat(){
        return this.floating;
    }
    public final void setFloat(boolean floating){
        this.floating = floating;
    }
    public final void setFloat(String floating){
        this.floating = ("true".equalsIgnoreCase(floating));
    }
    public final boolean isDisplayable() {
        return this.display.isNotNone();
    }
    public final boolean isInLayout() {
        return (!this.floating)&&(this.display.isNotNone());
    }
    public final boolean isCentered() {
        return this.centered;
    }
    public final boolean isNotCentered() {
        return (!this.centered);
    }
    public final void setCentered(boolean centered) {
        if (centered && (!this.centered))
            this.centered = true;
        else
            throw new IllegalStateException("Enable once only.");
    }
    public Font getFont(){
        Font font = this.font;
        if (null == font){
            Component parent = this.parent;
            if (null != parent)
                return parent.getFont();
        }
        return font;
    }
    public FontMetrics getFontMetrics(){
        FontMetrics fontMetrics = this.fontMetrics;
        if (null == fontMetrics){
            Font font = this.font;
            if (null != font){
                Toolkit tk = Toolkit.getDefaultToolkit();
                fontMetrics = tk.getFontMetrics(font);
                this.fontMetrics = fontMetrics;
            }
            else {
                Component parent = this.parent;
                if (null != parent)
                    return parent.getFontMetrics();
            }
        }
        return fontMetrics;
    }
    public final void setFont(Font b){
        if (null != b){
            this.font = b;
            this.fontMetrics = null;
        }
    }
    /**
     * @param string Syntax for Font Decode with spaces or hyphens.
     */
    public final void setFont(String string){
        if (null != string){
            string = string.trim().replace(' ','-');
            this.setFont(Font.decode(string));
        }
    }
    public Color getColor(){
        Color color = this.color;
        if (null == color){
            Component parent = this.parent;
            if (null != parent)
                return parent.getColor();
        }
        return color;
    }
    public Color darkenColor(){
        if (null == this.color){
            Component parent = this.parent;
            if (null != parent)
                return parent.darkenColor();
            else
                return null;
        }
        else {
            return (this.color = this.color.darker());
        }
    }
    public Color brightenColor(){
        if (null == this.color){
            Component parent = this.parent;
            if (null != parent)
                return parent.brightenColor();
            else
                return null;
        }
        else {
            return (this.color = this.color.brighter());
        }
    }
    public final void setColor(Color b){
        if (null != b)
            this.color = b;
    }
    public final void setColor(String string){
        if (null != string)
            this.setColor(CC.Decode(string));
    }
    public Color getBackgroundColor(){
        Color backgroundColor = this.backgroundColor;
        if (null == backgroundColor){
            Component parent = this.parent;
            if (null != parent)
                return parent.getBackgroundColor();
        }
        return backgroundColor;
    }
    public final void setBackgroundColor(Color b){
        if (null != b)
            this.backgroundColor = b;
    }
    public final void setBackgroundColor(String string){
        if (null != string)
            this.setBackgroundColor(CC.Decode(string));
    }
    public Color getSelectionColor(){
        Color selectionColor = this.selectionColor;
        if (null == selectionColor){
            Component parent = this.parent;
            if (null != parent)
                return parent.getSelectionColor();
        }
        return selectionColor;
    }
    public final void setSelectionColor(Color b){
        if (null != b)
            this.selectionColor = b;
    }
    public final void setSelectionColor(String string){
        if (null != string)
            this.setSelectionColor(CC.Decode(string));
    }
    public final Border getBorder(){
        return this.border;
    }
    public final void setBorder(Border b){
        if (null != b){
            this.border = b;
            Border f = this.getBorderFocused(b);
            b.setFocused(f);
        }
    }
    public final void setBorder(String string){
        if (null != string)
            this.setBorder(new Border(string));
    }
    public final Border getBorderFocused(Border b){

        Border f = this.borderFocused;
        if (null != f)
            return f;
        else {
            f = new Border(b,(b.width+0.6f));
            this.borderFocused = f;
            return f;
        }
    }
    public final Border getBorderFocused(){
        return this.borderFocused;
    }
    public final void setBorderFocused(Border b){
        if (null != b){
            this.borderFocused = b;
            this.border.setFocused(b);
        }
    }
    public final void setBorderFocused(String string){
        if (null != string)
            this.setBorderFocused(new Border(string));
    }
    public final Insets getPadding(){
        return this.padding;
    }
    public final void setPadding(Insets p){
        if (null != p)
            this.padding = p;
    }
    public final void setPadding(int m){
        if (-1 < m){
            this.padding.top = m;
            this.padding.left = m;
            this.padding.bottom = m;
            this.padding.right = m;
        }
    }
    public final void setPadding(String string){
        if (null != string){
            this.setPadding(new Insets(string));
        }
    }
    public final float getPaddingLeft(){
        return this.padding.left;
    }
    public final void setPaddingLeft(float v){
        this.padding.left = v;
    }
    public final float getPaddingRight(){
        return this.padding.right;
    }
    public final void setPaddingRight(float v){
        this.padding.right = v;
    }
    public final float getPaddingTop(){
        return this.padding.top;
    }
    public final void setPaddingTop(float v){
        this.padding.top = v;
    }
    public final float getPaddingBottom(){
        return this.padding.bottom;
    }
    public final void setPaddingBottom(float v){
        this.padding.bottom = v;
    }
    public final float getPaddingHorizontal(){
        return (this.padding.left+this.padding.right);
    }
    public final void setPaddingHorizontal(float v){
        this.padding.left = v;
        this.padding.right = v;
    }
    public final float getPaddingVertical(){
        return (this.padding.top+this.padding.bottom);
    }
    public final void setPaddingVertical(float v){
        this.padding.top = v;
        this.padding.bottom = v;
    }
    public final Insets getMargin(){
        return this.margin;
    }
    public final float getMarginTop(){
        return (this.margin.top);
    }
    public final float getMarginLeft(){
        return (this.margin.left);
    }
    public final float getMarginBottom(){
        return (this.margin.bottom);
    }
    public final float getMarginRight(){
        return (this.margin.right);
    }
    public final void setMarginTop(float v){
        this.margin.top = v;
    }
    public final void setMarginLeft(float v){
        this.margin.left = v;
    }
    public final void setMarginBottom(float v){
        this.margin.bottom = v;
    }
    public final void setMarginRight(float v){
        this.margin.right = v;
    }
    public final float getMarginHorizontal(){
        return (this.margin.left+this.margin.right);
    }
    public final float getMarginVertical(){
        return (this.margin.top+this.margin.bottom);
    }
    public final void setMarginHorizontal(float v){
        this.margin.left = v;
        this.margin.right = v;
    }
    public final void setMarginVertical(float v){
        this.margin.top = v;
        this.margin.bottom = v;
    }
    public final void setMargin(Insets p){
        if (null != p)
            this.margin = p;
    }
    public final void setMargin(float m){
        if (-1 < m){
            this.margin.top = m;
            this.margin.left = m;
            this.margin.bottom = m;
            this.margin.right = m;
        }
    }
    public final void setMargin(String string){
        if (null != string){
            this.setMargin(new Insets(string));
        }
    }
    public final Orientation getOrientation() {
        return this.orientation;
    }
    public final void setOrientation(Orientation o) {
        if (o != this.orientation){
            this.orientation = o;
            this.invalidate();
        }
    }
    public final void setOrientation(String orientation) {
        this.setOrientation(Orientation.decode(orientation));
    }
    public final boolean isOrientationHorizontal() {
        return (Orientation.HORIZONTAL == this.orientation);
    }
    public final boolean isOrientationVertical() {
        return (Orientation.VERTICAL == this.orientation);
    }
    public final void setOrientationHorizontal() {
        this.orientation = Orientation.HORIZONTAL;
    }
    public final void setOrientationHorizontal(boolean b) {
        if (b)
            this.orientation = Orientation.HORIZONTAL;
        else
            this.orientation = Orientation.VERTICAL;
    }
    public final void setOrientationVertical() {
        this.orientation = Orientation.VERTICAL;
    }
    public final void setOrientationVertical(boolean b) {
        if (b)
            this.orientation = Orientation.VERTICAL;
        else
            this.orientation = Orientation.HORIZONTAL;
    }
    public final boolean isViewNone(){
        return (View.None == this.view);
    }
    public final boolean isViewVertical(){
        return (View.Vertical == this.view);
    }
    public final boolean isViewHorizontal(){
        return (View.Horizontal == this.view);
    }
    public final boolean isViewAuto(){
        return (View.Auto == this.view);
    }
    public final View getView() {
        return this.view;
    }
    public final void setView(View o) {
        if (o != this.view){
            this.view = o;
            this.invalidate();
        }
    }
    public final void setView(String view) {
        this.setView(View.decode(view));
    }
    public final Display getDisplay() {
        return this.display;
    }
    public final void setDisplay(Display o) {
        if (!this.display.equals(o)){
            this.display = o;
            this.invalidate();
        }
    }
    public final void setDisplay(String display) {
        this.setDisplay(new Display(display));
    }
    public final void setDisplayNone(){
        this.display.setNone();
    }
    public final void setDisplayBlock(){
        this.display.setBlock();
    }
    public final String getTarget(){
        return this.target;
    }
    public final void setTarget(String target){
        this.target = target;
        this.targetComponent = null;
    }
    protected final boolean hasTargetComponent(){
        return (null != this.getTargetComponent());
    }
    protected final boolean hasNotTargetComponent(){
        return (null == this.getTargetComponent());
    }
    protected final Component getTargetComponent(){
        Component targetComponent = this.targetComponent;
        if (null == targetComponent){
            java.lang.Object targetObject = this.getTargetObject();
            if (targetObject instanceof Component){
                targetComponent = (Component)targetObject;
                this.targetComponent = targetComponent;
            }
        }
        return targetComponent;
    }
    protected final boolean hasTargetObject(){
        return (null != this.getTargetObject());
    }
    protected final java.lang.Object getTargetObject(){
        java.lang.Object targetObject = this.targetObject;
        if (null == targetObject){
            String id = this.target;
            if (null != id){
                targetObject = this.getObjectById(id);
                this.targetObject = targetObject;
            }
        }
        return targetObject;
    }
    public final boolean isAlignNone(){
        return (null == this.align);
    }
    public final boolean isAlignVertical(){
        if (null != this.align)
            return (Align.Top == this.align || Align.Bottom == this.align);
        else
            return false;
    }
    public final boolean isNotAlignVertical(){
        if (null != this.align)
            return (Align.Top != this.align && Align.Bottom != this.align);
        else
            return true;
    }
    public final boolean isAlignHorizontal(){
        if (null != this.align)
            return (Align.Left == this.align || Align.Right == this.align);
        else
            return false;
    }
    public final boolean isNotAlignHorizontal(){
        if (null != this.align)
            return (Align.Left != this.align && Align.Right != this.align);
        else
            return true;
    }
    public final boolean isAlignLeft(){
        return (Align.Left == this.align);
    }
    public final boolean isNotAlignLeft(){
        return (Align.Left != this.align);
    }
    public final boolean isAlignTop(){
        return (Align.Top == this.align);
    }
    public final boolean isNotAlignTop(){
        return (Align.Top != this.align);
    }
    public final boolean isAlignRight(){
        return (Align.Right == this.align);
    }
    public final boolean isNotAlignRight(){
        return (Align.Right != this.align);
    }
    public final boolean isAlignBottom(){
        return (Align.Bottom == this.align);
    }
    public final boolean isNotAlignBottom(){
        return (Align.Bottom != this.align);
    }
    public final boolean hasAlign() {
        return (null != this.align);
    }
    public final Align getAlign() {
        return this.align;
    }
    public final void setAlign(Align o) {
        if (o != this.align){
            this.align = o;
            this.invalidate();
        }
    }
    public final void setAlign(String align) {
        this.setAlign(Align.decode(align));
    }
    /**
     * Scan children in "Z order" for input -- inverse scene graph
     * order (last to first).  Note that "Z order" for paint is scene
     * graph order.
     */
    public Component getComponentAt(float x, float y) {
        for (Component child : this.inverse()){

            if (child.isVisible()) {
                Rectangle2D.Float bounds = child.getBounds2D();
                if (bounds.contains(x, y)) {
                    return child;
                }
            }
        }
        return null;
    }
    public Component getDescendantAt(float x, float y) {
        Component component = this.getComponentAt(x, y);
        if (null == component){

            return this;
        }
        else
            return component.getDescendantAt(x,y);
    }
    public final boolean isAncestor(Component c) {

        while (c != null) {

           if (c == this)
              return true;
           else
               c = c.parent;
        }
        return false;
    }
    /**
     * Maps a point in the local coordinate space to the ancestor's
     * coordinate system.
     */
    public final Point2D.Float mapPointToAncestor(Component ancestor, float x, float y) {

        if (ancestor != null){

            Component component = this;

            while (component != null) {
                if (component == ancestor) {
                    return (new Point2D.Float(x, y));
                }
                else {
                    x += component.x;
                    y += component.y;

                    component = component.parent;
                }
            }
        }
        return null;
    }
    /**
     * Maps a point in the specified ancestor's coordinate space to this
     * component's coordinate system.
     */
    public final Point2D.Float mapPointFromAncestor(Component ancestor, float x, float y) {
        if (ancestor != null){

            Component component = this;

            while (component != null) {
                if (component == ancestor)
                    return (new Point2D.Float(x, y));
                else {
                    x -= component.x;
                    y -= component.y;

                    component = component.parent;
                }
            }
        }
        return null;
    }

    /**
     * @return True for this and all ancestors visible 
     */
    public final boolean isVisibleAncestry() {

        if (this.isVisible()){
            Component component = this.parent;
            while (visible && null != component) {
                if (component.isNotVisible())
                    return false;
                else
                    component = component.parent;
            }
            return true;
        }
        else
            return false;
    }

    public final boolean isValid() {
        return this.valid;
    }
    /**
     * Mark invalid and propagate up to the root of the scene graph,
     * which then validates.
     * @see Scene#invalidate()
     */
    public void invalidate() {

        this.valid = false;
        Component parent = this.parent;
        if (null != parent)
            parent.invalidate();
    }
    public void validate() {

        this.valid = false;

        if (this.validateTopDown)
            this.validateTopDown();
        else
            this.validateBottomUp();

        if (this.loading){
            this.loading = false;
            this.requestFocus();
            this.onload(this);
        }
    }
    /**
     * Layout children and then this.
     */
    protected final boolean validateBottomUp() {
        if (this.hasChildren()){
            Rectangle2D.Float sum = this.getBoundsInside();
            Rectangle2D.Float copy = (Rectangle2D.Float)sum.clone();
            sum.x = 0f;
            sum.y = 0f;
            for (Component child : this){
                if (child.isDisplayable()){
                    child.validate();
                    sum.add(child.getBounds2D());
                }
            }

            float sw = sum.width;
            float sh = sum.height;
            if (sw > copy.width)
                this.setInnerWidth(sw);
            if (sh > copy.height)
                this.setInnerHeight(sh);
        }

        this.layout();

        this.effects.layout(this);

        this.valid = true;

        return true;
    }
    /**
     * Layout this and then children.
     */
    protected final boolean validateTopDown() {

        this.layout();

        for (Component child : this){
            if (child.isDisplayable()){
                child.validate();
            }
        }

        this.effects.layout(this);

        this.valid = true;

        return true;
    }
    public final Layout layoutAutoParentHorizontal(Component child){
        Component parent = this.parent;
        if (null == parent)
            return null;
        else
            return parent.layoutAutoHorizontal(child);
    }
    public final Layout layoutAutoHorizontal(Component child){
        int cidx = this.indexOf(child);
        if (0 > cidx)
            return null;
        else if (child.centered && child.isNotAlignHorizontal()){
            float inner = this.getInnerWidth();
            float dim ;

            if (child.hasRelative("width")){
                dim = inner-child.getMarginHorizontal();
                dim = child.getRelativeValue("width",dim).floatValue();
            }
            else if (child.hasWidth())
                dim = child.getWidth();
            else 
                dim = this.getInnerWidth()/2f;

            float pos = (inner - dim)/2f;
            return new Layout(pos,dim);
        }
        else {
            float innerDim = this.getInnerWidth();
            float ninlinDim = innerDim;
            float ninlinPos = this.padding.left;
            ninlinPos += child.getMarginLeft();
            ninlinDim -= child.getMarginHorizontal();

            if (child.hasRelative("width")){
                float relDim = child.getRelativeValue("width",innerDim).floatValue()-child.getMarginHorizontal();

                if (child.isNotAlignRight()){
                    float inlinePos = ninlinPos;

                    for (int prev = (cidx-1); -1 < prev; prev--){
                        Component oc = this.get(prev);
                        if (oc.isInLayout()){
                            inlinePos = (oc.x+oc.width+oc.margin.right)+child.margin.left;
                            break;
                        }
                    }
                    if ( (inlinePos+relDim) <= innerDim)
                        return new Layout(inlinePos,relDim);
                    else
                        return new Layout(ninlinPos,relDim);
                }
                else {
                    float alignPos = (innerDim - relDim - (child.margin.right+this.margin.right));
                    return new Layout(alignPos,relDim);
                }
            }
            else if (this.isOrientationHorizontal()){
                float inlineDim;
                if (child.hasWidthAuto())
                    inlineDim = child.getWidth();
                else {
                    inlineDim = ninlinDim;
                    for (int cc = 0, count = this.getLength(); cc < count; cc++){
                        if (cidx != cc){
                            Component oc = this.get(cc);
                            if (oc.isInLayout()){
                                inlineDim -= (oc.margin.left+oc.width+oc.margin.right);
                            }
                        }
                    }
                }
                if (0f < inlineDim){

                    if (child.isNotAlignRight()){
                        for (int prev = (cidx-1); -1 < prev; prev--){

                            Component oc = this.get(prev);
                            if (oc.isInLayout()){

                                float inlinePos = (oc.x+oc.width+oc.margin.right)+child.margin.left;

                                if ( (inlinePos+inlineDim) <= innerDim)
                                    return new Layout(inlinePos,inlineDim);
                            }
                        }
                        if ( (ninlinPos+inlineDim) <= innerDim)
                            return new Layout(ninlinPos,inlineDim);
                    }
                    else {
                        float alignPos = (innerDim - inlineDim - (child.margin.right+this.margin.right));
                        return new Layout(alignPos,inlineDim);
                    }
                }
            }
            return new Layout(ninlinPos,ninlinDim);
        }
    }
    public final Layout layoutAutoParentVertical(Component child){
        Component parent = this.parent;
        if (null == parent)
            return null;
        else
            return parent.layoutAutoVertical(child);
    }
    public final Layout layoutAutoVertical(Component child){
        int cidx = this.indexOf(child);
        if (0 > cidx)
            return null;
        else if (child.centered && child.isNotAlignVertical()){
            float inner = this.getInnerHeight();
            float dim ;

            if (child.hasRelative("height")){
                dim = inner-child.getMarginHorizontal();
                dim = child.getRelativeValue("height",dim).floatValue();
            }
            else if (child.hasHeight())
                dim = child.getHeight();
            else 
                dim = this.getInnerHeight()/2f;

            float pos = (inner - dim)/2f;
            return new Layout(pos,dim);
        }
        else {
            float innerDim = this.getInnerHeight();
            float ninlinDim = innerDim;
            float ninlinPos = this.padding.top;
            ninlinPos += child.getMarginTop();
            ninlinDim -= child.getMarginVertical();

            if (child.hasRelative("height")){
                float relDim = child.getRelativeValue("height",innerDim).floatValue()-child.getMarginVertical();

                if (child.isNotAlignBottom()){
                    float inlinePos = ninlinPos;

                    for (int prev = (cidx-1); -1 < prev; prev--){
                        Component oc = this.get(prev);
                        if (oc.isInLayout()){
                            inlinePos = (oc.y+oc.height+oc.margin.bottom)+child.margin.top;
                            break;
                        }
                    }
                    if ( (inlinePos+relDim) <= innerDim)
                        return new Layout(inlinePos,relDim);
                    else
                        return new Layout(ninlinPos,relDim);
                }
                else {
                    float alignPos = (innerDim - relDim - (child.margin.bottom+this.margin.bottom));
                    return new Layout(alignPos,relDim);
                }
            }
            else if (this.isOrientationVertical()){
                float inlineDim;
                if (child.hasHeightAuto())
                    inlineDim = child.getHeight();
                else {
                    inlineDim = ninlinDim;
                    for (int cc = 0, count = this.getLength(); cc < count; cc++){
                        if (cidx != cc){
                            Component oc = this.get(cc);
                            if (oc.isInLayout()){
                                inlineDim -= (oc.margin.top+oc.height+oc.margin.bottom);
                            }
                        }
                    }
                }
                if (0f < inlineDim){

                    if (child.isNotAlignBottom()){
                        for (int prev = (cidx-1); -1 < prev; prev--){

                            Component oc = this.get(prev);
                            if (oc.isInLayout()){

                                float inlinePos = (oc.y+oc.height+oc.margin.bottom)+child.margin.top;

                                if ( (inlinePos+inlineDim) <= innerDim)
                                    return new Layout(inlinePos,inlineDim);
                            }
                        }
                        if ( (ninlinPos+inlineDim) <= innerDim)
                            return new Layout(ninlinPos,inlineDim);
                    }
                    else {
                        float alignPos = (innerDim - inlineDim - (child.margin.bottom+this.margin.bottom));
                        return new Layout(alignPos,inlineDim);
                    }
                }
            }
            return new Layout(ninlinPos,ninlinDim);
        }
    }
    protected boolean layoutAutoPosX(){
        return (this.isInLayout())&&((this.autoPosX)||(0f == this.x)||this.hasRelative("x"));
    }
    protected boolean layoutAutoPosY(){
        return (this.isInLayout())&&((this.autoPosY)||(0f == this.y)||this.hasRelative("y"));
    }
    protected boolean layoutAutoDimW(){
        return (this.isInLayout())&&((this.autoDimW)||(0f == this.width)||this.hasRelative("width"));
    }
    protected boolean layoutAutoDimH(){
        return (this.isInLayout())&&((this.autoDimH)||(0f == this.height)||this.hasRelative("height"));
    }
    public void layout(){
        this.layoutAuto();
    }
    protected final void layoutAuto(){
        if (this.auto){
            this.autoPosX = this.layoutAutoPosX();
            this.autoPosY = this.layoutAutoPosY();
            this.autoDimW = this.layoutAutoDimW();
            this.autoDimH = this.layoutAutoDimH();

            Layout layout;
            if (this.autoDimH || this.autoPosY){
                layout = this.layoutAutoParentVertical(this);
                if (this.autoPosY){
                    this.setY(layout.pos);
                    if (this.autoDimH)
                        this.setHeight(layout.dim);
                }
                else if (this.autoDimH)
                    this.setHeight(layout.dim);
            }
            if (this.autoDimW || this.autoPosX){
                layout = this.layoutAutoParentHorizontal(this);
                if (this.autoPosX){
                    this.setX(layout.pos);
                    if (this.autoDimW)
                        this.setWidth(layout.dim);
                }
                else if (this.autoDimW){
                    this.setWidth(layout.dim);
                }
            }
        }
    }
    protected void layoutView(Rectangle2D.Float view){
        if (View.Vertical == this.view){
            Rectangle2D.Float viewport = this.getBoundsInside();
            if (viewport.contains(view)){
                if (null != this.scrolling){
                    this.scrolling = null;
                    this.repaint();
                }
            }
            else {
                if (null == this.scrolling){
                    this.scrolling = new Scrolling(this);
                }
                this.scrolling.update(viewport,view);
            }
        }
        else
            this.scrolling = null;
    }

    public final boolean isEnabled() {
        return this.enabled;
    }
    public final boolean isNotEnabled(){
        return (!this.isEnabled());
    }
    public final void setEnabled(boolean enabled) {
        if (this.enabled != enabled) {
            if (!enabled) {

                if (isFocused() || containsFocus()) {
                    ClearFocus();
                }

                if (mouseOver) {
                    mouseOut();
                }
            }

            this.enabled = enabled;
        }
    }
    public final boolean isEnabledAncestry() {
        boolean notEnabledAncestry = true;

        Component component = this;

        do {
            notEnabledAncestry = component.isEnabled();
            component = component.parent;
        }
        while (component != null && notEnabledAncestry);

        return (!notEnabledAncestry);
    }
    public final boolean isNotEnabledAncestry(){
        return (!this.isEnabledAncestry());
    }
    public final boolean isMouseOver() {
        return mouseOver;
    }
    public Cursor getCursor() {
        return cursor;
    }
    public final void setCursor(Cursor cursor) {
        Cursor previousCursor = this.cursor;

        if (previousCursor != cursor) {
            this.cursor = cursor;

            if (mouseOver) {
                Mouse.setCursor(this);
            }
        }
    }
    public final void setCursor(String cursor) {
        setCursor((cursor == null) ? null : Cursor.decode(cursor));
    }
    public final boolean isFocusable() {
        if (this.enabled && this.visible && this.focusableComponent)
            return (this.isNotEnabledAncestry() && this.isVisibleAncestry());
        else
            return false;
    }
    public final boolean isNotFocusable() {
        return (!this.isFocusable());
    }
    public final boolean isFocused() {

        return (this == FocusedComponent);
    }
    public final boolean isNotFocused() {

        return (this != FocusedComponent);
    }
    public final boolean containsFocus() {

        return (this.isAncestor(FocusedComponent));
    }
    public void focusChanged(boolean in){

        this.border.focusChanged(in);

        if (in)
            this.onfocus(this);

        else 
            this.onblur(this);

        this.repaint();
    }
    public void requestFocus(){
        this.findFocus(Direction.Forward);
    }
    protected final boolean requestFocusComponent(){
        SetFocusedComponent(this);
        this.getScene().requestFocus();
        return true;
    }
    public final boolean findFocus(Direction direction){
        if (this.isFocusable())
            return this.requestFocusComponent();
        else {
            if (Direction.Forward == direction){
                for (Component child : this){
                    if (child.findFocus(direction))
                        return true;
                }
            }
            else {
                for (Component child : this.inverse()){
                    if (child.findFocus(direction))
                        return true;
                }
            }
            return false;
        }
    }
    public boolean transferFocus(Direction direction) {

        if (this.isFocusable()){
            if (this.isFocused()){
                Component parent = this.parent;
                Component visited, sibling = this;
                boolean ascended = false;
                do {
                    visited = sibling;
                    sibling = parent.getSibling(visited, direction);
                    {
                        while (null != sibling && sibling != visited){
                            if (ascended){
                                if (sibling.findFocus(direction))
                                    return true;
                                else
                                    sibling = parent.getSibling(sibling, direction);
                            }
                            else {
                                if (sibling.transferFocus(direction))
                                    return true;
                                else
                                    sibling = parent.getSibling(sibling, direction);
                            }
                        }
                    }
                    sibling = parent;
                    parent = parent.parent;
                    ascended = true;
                }
                while (null != parent);

                return false;
            }
            else
                return SetFocusedComponent(this);
        }
        else 
            return false;
    }
    public Component getSibling(Component component, Direction direction){
        if (null == component){
            if (Direction.Forward == direction)
                return this.first();
            else
                return this.last();
        }
        else {
            int len = this.getLength();
            if (1 == len)
                return null;
            else {
                int idx = this.indexOf(component);
                if (0 > idx)
                    return null;

                else if (Direction.Forward == direction){
                    idx += 1;
                    if (idx >= len)
                        return null;
                    else
                        return this.get(idx);
                }
                else {
                    idx -= 1;
                    if (0 > idx)
                        return null;
                    else
                        return this.get(idx);
                }
            }
        }
    }
    public DragSource getDragSource() {
        return dragSource;
    }
    public void setDragSource(DragSource dragSource) {
        DragSource previousDragSource = this.dragSource;

        if (previousDragSource != dragSource) {
            this.dragSource = dragSource;
        }
    }
    public DropTarget getDropTarget() {
        return dropTarget;
    }
    public void setDropTarget(DropTarget dropTarget) {
        DropTarget previousDropTarget = this.dropTarget;

        if (previousDropTarget != dropTarget) {
            this.dropTarget = dropTarget;
        }
    }
    public Dictionary<String, ?> getStyle() {
        return this.getReflect();
    }
    public void setStyle(Dictionary<String, ?> style) {
        if (null != style){
            Reflector reflect = this.getReflect();
            for (String key : style) {
                reflect.put(key, style.get(key));
            }
        }
    }
    public void setStyle(URL url) throws IOException {
        if (null != url) {

            Resolver context = Resolver.Get();

            CSS css;
            if (null != context)
                css = new CSS(context);
            else
                css = new CSS(this.getScene(),this.getProperties());

            Dictionary<String, ?> atts = (Dictionary<String,?>)css.readObject(url);

            Reflector reflect = this.getReflect();

            reflect.applyAttributes(css,atts);
        }
    }
    public void setStyle(String style) {
        if (null != style) {

            Resolver context = Resolver.Get();

            CSS css;
            if (null != context)
                css = new CSS(context);
            else
                css = new CSS(this.getScene(),this.getProperties());

            try {
                Dictionary<String, ?> atts = css.parse(style);

                Reflector reflect = this.getReflect();

                reflect.applyAttributes(css,atts);
            }
            catch (IOException exc){
                throw new IllegalArgumentException(style,exc);
            }
        }
    }
    public boolean hasScrolling(){
        return (null != this.scrolling);
    }
    public Scrolling getScrolling(){
        return this.scrolling;
    }


    public void repaint() {
        this.repaint(0f, 0f, this.width, this.height);
    }
    public final void repaint(Rectangle2D r){
        if (null != r){
            if (r instanceof Rectangle2D.Float){
                Rectangle2D.Float rf = (Rectangle2D.Float)r;
                this.repaint(rf.x,rf.y,rf.width,rf.height);
            }
            else {
                Rectangle2D.Double rd = (Rectangle2D.Double)r;
                float x = (float)rd.x;
                float y = (float)rd.y;
                float w = (float)rd.width;
                float h = (float)rd.height;
                this.repaint(x,y,w,h);
            }
        }
    }
    public final void repaint(Rectangle2D.Float r){
        if (null != r){
            this.repaint(r.x,r.y,r.width,r.height);
        }
    }
    public void repaint(float x, float y, float width, float height){
        Component parent = this.parent;
        if (parent != null) {

            float bottom = (y + height - 1f);
            float right = (x + width - 1f);

            x = Math.max(x, 0);
            y = Math.max(y, 0);
            width = Math.min(right, this.width - 1) - x + 1;
            height = Math.min(bottom, this.height - 1) - y + 1;

            if (width > 0 && height > 0) {

                Rectangle2D.Float tran = this.effects.getTransformedBounds(this, x, y, width, height);
                if (null != tran){

                    tran.x += this.x;
                    tran.y += this.y;

                    parent.repaint(tran.x, tran.y, tran.width, tran.height);
                }
                else {
                    x += this.x;
                    y += this.y;
                    
                    parent.repaint(x, y, width, height);
                }
            }
        }
    }
    /**
     * Redefine this method as desired.  
     * 
     * @param g  Local coordinates
     */
    public void paint(Graphics2D g) {

        this.border.fill(this,g);

        g.setStroke(DefaultStroke);

        this.paintContainer(g);
    }
    protected final Graphics2D createEffecting(Graphics2D g){

        Rectangle b = this.getBoundsEffecting();

        if (g.hitClip(b.x,b.y,b.width,b.height))
            return (Graphics2D)g.create(b.x,b.y,b.width,b.height);
        else
            return null;
    }
    protected final Graphics2D createComponentUneffecting(Graphics2D g){
        if (!this.valid)
            throw new RepaintJump.Validating();
        else {
            int x = (int)this.x;
            int y = (int)this.y;
            int w = (int)this.width;
            int h = (int)this.height;
            if (g.hitClip(x,y,w,h))
                return (Graphics2D)g.create(x,y,w,h);
            else
                return null;
        }
    }
    protected final Graphics2D createComponentEffecting(Graphics2D gd){
        if (!this.valid)
            throw new RepaintJump.Validating();
        else {
            int x = (int)this.componentEffectingX;
            int y = (int)this.componentEffectingY;
            int w = (int)this.width;
            int h = (int)this.height;
            if (gd.hitClip(x,y,w,h))
                return (Graphics2D)gd.create(x,y,w,h);
            else
                return null;
        }
    }
    protected final void paintComponentUneffecting(Graphics2D g) {

        Graphics2D cg = this.createComponentUneffecting(g);
        if (null != cg){
            try {
                this.paint(cg);
            }
            finally {
                cg.dispose();
            }
        }
    }
    protected final void paintComponentEffecting(Graphics2D gd) {

        Graphics2D cg = this.createComponentEffecting(gd);
        if (null != cg){
            try {
                this.paint(cg);
            }
            finally {
                cg.dispose();
            }
        }
    }
    protected final void paintComponent(Graphics2D g) {

        if (this.hasEffects()){
            Graphics2D gd = this.createEffecting(g);
            if (null != gd){
                try {
                    gd = this.effects.prepare(this,gd);

                    this.paintComponentEffecting(gd);
                }
                finally {
                    if (gd != g)
                        gd.dispose();
                }
                this.effects.update(g);
            }
        }
        else
            this.paintComponentUneffecting(g);
    }
    protected final void paintContainer(Graphics2D g) {

        for (Component child : this) {

            if (child.isVisible()){

                child.paintComponent(g);
            }
        }
    }

    public boolean mouseMove(float x, float y) {
        if (this.enabled)
            return this.onmousemove(this,x,y);
        else
            return false;
    }
    public void mouseOver() {
        if (this.enabled) {
            this.onmouseover(this);
            this.mouseOver = true;
        }
    }
    public void mouseOut() {
        if (this.enabled) {
            this.onmouseout(this);
            this.mouseOver = false;
        }
    }
    public boolean mouseDown(Mouse.Button button, float x, float y) {
        if (this.enabled)
            return this.onmousedown(this,button,x,y);
        else
            return false;
    }
    public boolean mouseUp(Mouse.Button button, float x, float y) {
        if (this.enabled)
            return this.onmouseup(this,button,x,y);
        else
            return false;
    }
    public boolean mouseClick(Mouse.Button button, float x, float y, int count) {
        if (this.enabled){
            if (1 < count)
                return this.ondblclick(this,button,x,y);
            else
                return this.onclick(this,button,x,y);
        }
        else
            return false;
    }
    public boolean mouseWheel(Mouse.ScrollType scroll, int amount, int rot, float x, float y)
    {
        if (this.enabled)
            return this.onmousewheel(this,scroll,amount,rot,x,y);
        else
            return false;
    }
    public boolean keyTyped(char character) {
        if (this.enabled) {
            if (this.onkeypress(this,character))
                return true;
            else {
                Component parent = this.parent;
                if (null != parent)
                    return parent.keyTyped(character);
            }
        }
        return false;
    }
    public boolean keyPressed(int code, Keyboard.KeyLocation location) {
        if (this.enabled) {
            if (this.transfersFocus){
                if (Keyboard.KeyCode.TAB == code){
                    if (Keyboard.isPressed(Keyboard.Modifier.SHIFT)){
                        if (this.transferFocus(Direction.Backward)){
                            return true;
                        }
                    }
                    else if (this.transferFocus(Direction.Forward)){
                        return true;
                    }
                }
            }

            if (this.onkeydown(this,code,location))
                return true;
            else {
                Component parent = this.parent;
                if (null != parent)
                    return this.parent.keyPressed(code, location);
            }
        }
        return false;
    }
    public boolean keyReleased(int code, Keyboard.KeyLocation location) {
        if (this.enabled) {
            if (this.onkeyup(this,code,location))
                return true;
            else {
                Component parent = this.parent;
                if (null != parent)
                    return parent.keyReleased(code, location);
            }
        }
        return false;
    }

    public final Function getOnload(){
        return this.fOnload;
    }
    public final Component setOnload(Function fun){
        this.fOnload = fun;
        return this;
    }
    public final Component setOnload(String fn){
        return this.setOnload(new Function(this,Function.Type.onload,fn));
    }
    public final boolean onload(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnload;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnunload(){
        return this.fOnunload;
    }
    public final Component setOnunload(Function fun){
        this.fOnunload = fun;
        return this;
    }
    public final Component setOnunload(String fn){
        return this.setOnunload(new Function(this,Function.Type.onunload,fn));
    }
    public final boolean onunload(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnunload;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnclick(){
        return this.fOnclick;
    }
    public final Component setOnclick(Function fun){
        this.fOnclick = fun;
        return this;
    }
    public final Component setOnclick(String fn){
        return this.setOnclick(new Function(this,Function.Type.onclick,fn));
    }
    public final boolean onclick(Component thi, Mouse.Button button, float x, float y)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnclick;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,button,x,y);
            else
                re = fun.invoke(thi,button,x,y);

            if (re instanceof Boolean){

                if ( ((Boolean)re).booleanValue()){
                    if (this.submit){
                        Form form = this.getForm();
                        if (null != form)
                            form.submit();
                    }
                    return true;
                }
            }
        }
        return false;
    }
    public final Function getOndblclick(){
        return this.fOndblclick;
    }
    public final Component setOndblclick(Function fun){
        this.fOndblclick = fun;
        return this;
    }
    public final Component setOndblclick(String fn){
        return this.setOndblclick(new Function(this,Function.Type.ondblclick,fn));
    }
    public final boolean ondblclick(Component thi, Mouse.Button button, float x, float y)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOndblclick;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,button,x,y);
            else
                re = fun.invoke(thi,button,x,y);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnmousedown(){
        return this.fOnmousedown;
    }
    public final Component setOnmousedown(Function fun){
        this.fOnmousedown = fun;
        return this;
    }
    public final Component setOnmousedown(String fn){
        return this.setOnmousedown(new Function(this,Function.Type.onmousedown,fn));
    }
    public final boolean onmousedown(Component thi, Mouse.Button button, float x, float y)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnmousedown;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,button,x,y);
            else
                re = fun.invoke(thi,button,x,y);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnmouseup(){
        return this.fOnmouseup;
    }
    public final Component setOnmouseup(Function fun){
        this.fOnmouseup = fun;
        return this;
    }
    public final Component setOnmouseup(String fn){
        return this.setOnmouseup(new Function(this,Function.Type.onmouseup,fn));
    }
    public final boolean onmouseup(Component thi, Mouse.Button button, float x, float y)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnmouseup;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,button,x,y);
            else
                re = fun.invoke(thi,button,x,y);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnmouseover(){
        return this.fOnmouseover;
    }
    public final Component setOnmouseover(Function fun){
        this.fOnmouseover = fun;
        return this;
    }
    public final Component setOnmouseover(String fn){
        return this.setOnmouseover(new Function(this,Function.Type.onmouseover,fn));
    }
    public final boolean onmouseover(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnmouseover;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnmousemove(){
        return this.fOnmousemove;
    }
    public final Component setOnmousemove(Function fun){
        this.fOnmousemove = fun;
        return this;
    }
    public final Component setOnmousemove(String fn){
        return this.setOnmousemove(new Function(this,Function.Type.onmousemove,fn));
    }
    public final boolean onmousemove(Component thi, float x, float y)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnmousemove;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,x,y);
            else
                re = fun.invoke(thi,x,y);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnmouseout(){
        return this.fOnmouseout;
    }
    public final Component setOnmouseout(Function fun){
        this.fOnmouseout = fun;
        return this;
    }
    public final Component setOnmouseout(String fn){
        return this.setOnmouseout(new Function(this,Function.Type.onmouseout,fn));
    }
    public final boolean onmouseout(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnmouseout;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnmousewheel(){
        return this.fOnmousewheel;
    }
    public final Component setOnmousewheel(Function fun){
        this.fOnmousewheel = fun;
        return this;
    }
    public final Component setOnmousewheel(String fn){
        return this.setOnmousewheel(new Function(this,Function.Type.onmousewheel,fn));
    }
    public final boolean onmousewheel(Component thi, Mouse.ScrollType scroll, int amount, int rot, float x, float y)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnmousewheel;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,scroll,amount,rot,x,y);
            else
                re = fun.invoke(thi,scroll,amount,rot,x,y);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnfocus(){
        return this.fOnfocus;
    }
    public final Component setOnfocus(Function fun){
        this.fOnfocus = fun;
        return this;
    }
    public final Component setOnfocus(String fn){
        return this.setOnfocus(new Function(this,Function.Type.onfocus,fn));
    }
    public final boolean onfocus(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnfocus;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnblur(){
        return this.fOnblur;
    }
    public final Component setOnblur(Function fun){
        this.fOnblur = fun;
        return this;
    }
    public final Component setOnblur(String fn){
        return this.setOnblur(new Function(this,Function.Type.onblur,fn));
    }
    public final boolean onblur(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnblur;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnkeypress(){
        return this.fOnkeypress;
    }
    public final Component setOnkeypress(Function fun){
        this.fOnkeypress = fun;
        return this;
    }
    public final Component setOnkeypress(String fn){
        return this.setOnkeypress(new Function(this,Function.Type.onkeypress,fn));
    }
    public final boolean onkeypress(Component thi, char ch)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnkeypress;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,ch);
            else
                re = fun.invoke(thi,ch);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnkeydown(){
        return this.fOnkeydown;
    }
    public final Component setOnkeydown(Function fun){
        this.fOnkeydown = fun;
        return this;
    }
    public final Component setOnkeydown(String fn){
        return this.setOnkeydown(new Function(this,Function.Type.onkeydown,fn));
    }
    public final boolean onkeydown(Component thi, int code, Keyboard.KeyLocation location)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnkeydown;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,code,location);
            else
                re = fun.invoke(thi,code,location);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnkeyup(){
        return this.fOnkeyup;
    }
    public final Component setOnkeyup(Function fun){
        this.fOnkeyup = fun;
        return this;
    }
    public final Component setOnkeyup(String fn){
        return this.setOnkeyup(new Function(this,Function.Type.onkeyup,fn));
    }
    public final boolean onkeyup(Component thi, int code, Keyboard.KeyLocation location)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnkeyup;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target,code,location);
            else
                re = fun.invoke(thi,code,location);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnsubmit(){
        return this.fOnsubmit;
    }
    public final Component setOnsubmit(Function fun){
        this.fOnsubmit = fun;
        return this;
    }
    public final Component setOnsubmit(String fn){
        return this.setOnsubmit(new Function(this,Function.Type.onsubmit,fn));
    }
    public final boolean onsubmit(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnsubmit;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnreset(){
        return this.fOnreset;
    }
    public final Component setOnreset(Function fun){
        this.fOnreset = fun;
        return this;
    }
    public final Component setOnreset(String fn){
        return this.setOnreset(new Function(this,Function.Type.onreset,fn));
    }
    public final boolean onreset(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnreset;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnselect(){
        return this.fOnselect;
    }
    public final Component setOnselect(Function fun){
        this.fOnselect = fun;
        return this;
    }
    public final Component setOnselect(String fn){
        return this.setOnselect(new Function(this,Function.Type.onselect,fn));
    }
    public final boolean onselect(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnselect;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }
    public final Function getOnchange(){
        return this.fOnchange;
    }
    public final Component setOnchange(Function fun){
        this.fOnchange = fun;
        return this;
    }
    public final Component setOnchange(String fn){
        return this.setOnchange(new Function(this,Function.Type.onchange,fn));
    }
    public final boolean onchange(Component thi)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fOnchange;
        if (null != fun){
            java.lang.Object re;
            Component target = this.getTargetComponent();
            if (null != target)
                re = fun.invoke(target);
            else
                re = fun.invoke(thi);

            if (re instanceof Boolean)
                return ((Boolean)re).booleanValue();
        }
        return false;
    }

    public final Function getResponse(){
        return this.fResponse;
    }
    public final Component setResponse(Function fun){
        this.fResponse = fun;
        return this;
    }
    public final Component setResponse(String fn){
        return this.setResponse(new Function(this,Function.Type.response,fn));
    }
    /**
     * Normal XHR response handler.
     */
    public final void response(Component thi, wtkx.io.XMLHttpRequest xhr)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fResponse;
        if (null != fun)
            fun.invoke(thi,xhr);
    }
    public final Function getRequest(){
        return this.fRequest;
    }
    public final Component setRequest(Function fun){
        this.fRequest = fun;
        return this;
    }
    public final Component setRequest(String fn){
        return this.setRequest(new Function(this,Function.Type.request,fn));
    }
    /**
     * Invoked on a completely populated XHR immediately before the
     * first network communication.  Permits authentication. 
     */
    public final void request(Component thi, wtkx.io.XMLHttpRequest xhr)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        Function fun = this.fRequest;
        if (null != fun)
            fun.invoke(thi,xhr);
    }

    public final Function getWriter(){
        return this.fWriter;
    }
    public final Component setWriter(Function fun){
        this.fWriter = fun;
        return this;
    }
    public final Component setWriter(String fn){
        return this.setWriter(new Function(this,Function.Type.writer,fn));
    }
    /**
     * Synchronous output binding permits authentication.
     */
    public final wtkx.io.UrlcOutputStream writer(Component thi, java.net.URLConnection urlc)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        urlc.setUseCaches(false);
        urlc.setRequestProperty("Pragma","no-cache");
        urlc.setRequestProperty("Cache-Control","no-cache");

        Function fun = this.fWriter;
        if (null != fun)
            return (wtkx.io.UrlcOutputStream)fun.invoke(thi,urlc);
        else {
            try {
                urlc.setDoOutput(true);
                return new wtkx.io.UrlcOutputStream(urlc);
            }
            catch (java.net.UnknownServiceException exc){
                java.net.URL url = urlc.getURL();
                if ("file".equals(url.getProtocol())){
                    try {
                        return new wtkx.io.UrlcOutputStream(urlc,new java.io.File(url.getPath()));
                    }
                    catch (IOException exc0){
                        throw new Function.InvokeErrorTarget(exc);
                    }
                }
                else
                    throw new Function.InvokeErrorTarget(exc);
            }
            catch (java.io.IOException exc){
                throw new Function.InvokeErrorTarget(exc);
            }
        }
    }
    public final Function getReader(){
        return this.fReader;
    }
    public final Component setReader(Function fun){
        this.fReader = fun;
        return this;
    }
    public final Component setReader(String fn){
        return this.setReader(new Function(this,Function.Type.reader,fn));
    }
    /**
     * Synchronous input binding permits authentication.
     */
    public final wtkx.io.UrlcInputStream reader(Component thi, java.net.URLConnection urlc)
        throws Function.InvokeErrorAccess, Function.InvokeErrorTarget,
               Function.InvokeErrorNotInitialized
    {
        urlc.setUseCaches(false);
        urlc.setRequestProperty("Pragma","no-cache");
        urlc.setRequestProperty("Cache-Control","no-cache");

        Function fun = this.fReader;
        if (null != fun)
            return (wtkx.io.UrlcInputStream)fun.invoke(thi,urlc);
        else {
            try {
                return new wtkx.io.UrlcInputStream(urlc);
            }
            catch (java.io.IOException exc){
                throw new Function.InvokeErrorTarget(exc);
            }
        }
    }

    /**
     * @param a Functions' instance object, typically either
     * application or this.
     */
    public final void initFunctions(Application a, Function.List methods)
        throws Function.MethodNotFound
    {
        Function fun;
        fun = this.fOnload;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnunload;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnclick;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOndblclick;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmousedown;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmouseup;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmouseover;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmousemove;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmouseout;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmousewheel;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnfocus;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnblur;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnkeypress;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnkeydown;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnkeyup;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnsubmit;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnreset;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnselect;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnchange;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fResponse;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fRequest;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fReader;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fWriter;
        if (null != fun)
            fun.init(a,methods);

        for (Component child : this){
            child.initFunctions(a,methods);
        }
    }
    /**
     * @param a Functions' instance object from target.
     */
    public final void initFunctions(java.lang.Object a, Function.List methods)
        throws Function.MethodNotFound
    {
        Function fun;
        fun = this.fOnload;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnunload;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnclick;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOndblclick;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmousedown;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmouseup;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmouseover;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmousemove;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmouseout;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnmousewheel;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnfocus;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnblur;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnkeypress;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnkeydown;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnkeyup;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnsubmit;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnreset;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnselect;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fOnchange;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fResponse;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fRequest;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fReader;
        if (null != fun)
            fun.init(a,methods);
        fun = this.fWriter;
        if (null != fun)
            fun.init(a,methods);

        for (Component child : this){
            child.initFunctions(a,methods);
        }
    }
    /**
     * Must be called from the application startup.
     */
    public void init(Application a)
        throws Function.MethodNotFound
    {
        this.application = application;
        this.loading = true;

        if (this.hasTargetObject() && this.hasNotTargetComponent()){
            java.lang.Object target = this.getTargetObject();
            if (target instanceof wtkx.Object){
                target = ((wtkx.Object)target).getValue();
                if (null == target)
                    throw new IllegalStateException("Unbound target '"+this.target+"'.");
            }

            Function.List methods = new Function.List(target.getClass());
            this.initFunctions(target,methods);
        }
        else {
            Function.List methods = new Function.List(a.getClass());
            this.initFunctions(a,methods);
        }
    }
    public void borderDebug(){
        this.border.setDebug();
        for (Component child : this)
            child.borderDebug();
    }
    public String toString(){
        return this.identityString;
    }
}
